package com.nhim.cms.admin.client.group.ui;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.activity.shared.Activity;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.HasKeyboardPagingPolicy.KeyboardPagingPolicy;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.nhim.cms.admin.client.ScrollablePagerPanel;
import com.nhim.cms.admin.client.group.ui.GroupContentTypeSelection.Listener;
import com.nhim.cms.admin.client.place.GroupListPlace;
import com.nhim.cms.admin.client.rpc.ContentTypeRPCService;
import com.nhim.cms.admin.client.rpc.ContentTypeRPCServiceAsync;
import com.nhim.cms.admin.client.style.Styles;
import com.nhim.cms.admin.shared.ContentTypeRPCProxy;
import com.nhim.cms.admin.shared.GroupProxy;
import com.nhim.cms.admin.shared.GroupRequest;
import com.nhim.cms.admin.shared.NhimCMSAdminRequestFactory;

public class GroupList extends Composite implements Activity {

	private static GroupListUiBinder uiBinder = GWT
			.create(GroupListUiBinder.class);
	private final NhimCMSAdminRequestFactory requestFactory;
	private final ContentTypeRPCServiceAsync service = GWT
			.create(ContentTypeRPCService.class);

	interface GroupListUiBinder extends UiBinder<Widget, GroupList> {

	}

	public GroupList(NhimCMSAdminRequestFactory requestFactory) {
		initWidget(uiBinder.createAndBindUi(this));
		this.requestFactory = requestFactory;
		ltContentTypes.setVisibleItemCount(15);
		ltContentTypes.setWidth("32em");
		editPanel.setVisible(false);
		overviewPanel.setVisible(true);
		btnDelete.setVisible(false);
		btnSave.setVisible(false);
		divImage.setInnerHTML(AbstractImagePrototype.create(
				Styles.resources().group()).getHTML());

	}

	@UiField
	Button btnSave;
	@UiField
	Button btnDelete;
	@UiField
	Button btnNew;
	@UiField
	Anchor btnEdit;
	@UiField
	TextBox txtName;
	@UiField
	TextBox txtDescription;
	@UiField
	ScrollablePagerPanel pagerPanel;
	@UiField
	com.google.gwt.user.client.ui.HTMLPanel editPanel;
	@UiField
	com.google.gwt.user.client.ui.HTMLPanel overviewPanel;
	@UiField
	SpanElement totalsGroupSpan;
	@UiField
	DivElement divImage;

	GroupProxy selectedGroupProxy;

	@UiField
	ListBox ltContentTypes;

	private boolean running;

	private void clearForm() {
		txtName.setText("");
		txtDescription.setText("");
		ltContentTypes.clear();
	}

	/**
	 * In this application, called by {@link ExpensesActivityMapper} each time a
	 * ReportListPlace is posted. In a more typical set up, this would be a
	 * constructor argument to a one shot activity, perhaps managing a shared
	 * widget view instance.
	 */
	public void updateForPlace(final GroupListPlace place) {
		if (running) {
			doUpdateForPlace();
		}
	}

	public String mayStop() {
		return null;
	}

	public void onCancel() {
		onStop();
	}

	public void onStop() {
		running = false;

	}

	public void start(AcceptsOneWidget panel, EventBus arg1) {
		running = true;
		doUpdateForPlace();
		panel.setWidget(this);

	}


	private void doUpdateForPlace() {

		// Create a CellList.
		GroupCell customWidgetInstanceCell = new GroupCell();

		// Set a key provider that provides a unique key for each
		// CustomWidgetInstance. If key is
		// used to identify CustomWidgetInstances when fields (such as the name
		// and description)
		// change.
		cellList = new CellList<GroupProxy>(customWidgetInstanceCell,
				KEY_PROVIDER);
		cellList.setPageSize(30);
		cellList.setKeyboardPagingPolicy(KeyboardPagingPolicy.INCREASE_RANGE);
		cellList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.BOUND_TO_SELECTION);

		cellList.setSelectionModel(selectionModel);
		selectionModel
				.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
					public void onSelectionChange(SelectionChangeEvent event) {
						selectedGroupProxy = selectionModel.getSelectedObject();
						clearForm();
						isNew = false;
						btnDelete.setVisible(true);
						btnEdit.setVisible(true);
						editPanel.setVisible(true);
						overviewPanel.setVisible(false);
						btnSave.setVisible(true);
						txtName.setText(selectedGroupProxy.getName());
						txtDescription.setText(selectedGroupProxy
								.getDescription());
						service.findByGroupId(
								selectedGroupProxy.getId(),
								new AsyncCallback<ArrayList<ContentTypeRPCProxy>>() {

									public void onFailure(Throwable e) {
										Window.alert("There was an error while fetching ContentTypes.");

									}

									public void onSuccess(
											ArrayList<ContentTypeRPCProxy> results) {
										ltContentTypes.clear();
										for (ContentTypeRPCProxy proxy : results) {
											ltContentTypes.addItem(proxy
													.getName(), proxy.getId()
													.toString());
										}

									}
								});
					}
				});

		pagerPanel.setDisplay(cellList);
		dataProvider.addDataDisplay(cellList);
		final List<GroupProxy> data = dataProvider.getList();
		data.clear();
		requestFactory.groupRequest().findAll()
				.fire(new Receiver<List<GroupProxy>>() {
					@Override
					public void onFailure(ServerFailure error) {
						Window.alert("There was an error while fetching groups.");
					}

					@Override
					public void onSuccess(List<GroupProxy> results) {
						totalsGroupSpan.setInnerText(results.size() + " groups");
						data.clear();
						data.addAll(results);
					}
				});
		cellList.redraw();

	}

	/**
	 * The Cell used to render a {@link GroupCell}.
	 */
	static class GroupCell extends AbstractCell<GroupProxy> {

		public GroupCell() {

		}

		@Override
		public void render(com.google.gwt.cell.client.Cell.Context arg0,
				GroupProxy value, SafeHtmlBuilder sb) {

			// Value can be null, so do a null check..
			if (value == null) {
				return;
			}

			sb.appendHtmlConstant("<table>");

			// Add the content type image.
			sb.appendHtmlConstant("<tr>");

			// Add the name and description.
			sb.appendHtmlConstant("<td style='font-size:95%;'>");
			sb.appendEscaped(value.getName());
			sb.appendHtmlConstant("</td></tr><tr><td style='text-align: right; font-style: italic; color: #666666;'>");
			sb.appendEscaped(value.getDescription());
			sb.appendHtmlConstant("</td></tr></table>");
		}

	}

	/**
	 * The CellList.
	 */
	private CellList<GroupProxy> cellList;
	// Add a selection model so we can select cells.
	SingleSelectionModel<GroupProxy> selectionModel = new SingleSelectionModel<GroupProxy>(
			KEY_PROVIDER);

	private ListDataProvider<GroupProxy> dataProvider = new ListDataProvider<GroupProxy>();

	/**
	 * The key provider that provides the unique ID of a contentType.
	 */
	public static final ProvidesKey<GroupProxy> KEY_PROVIDER = new ProvidesKey<GroupProxy>() {
		public Object getKey(GroupProxy item) {
			return item == null ? null : item.getId();
		}
	};

	/**
	 * The resources applied to the table.
	 */
	interface TableResources extends CellTable.Resources {
		@Source({ CellTable.Style.DEFAULT_CSS,
				"../../style/normalCellTable.css" })
		TableStyle cellTableStyle();
	}

	/**
	 * The styles applied to the table.
	 */
	interface TableStyle extends CellTable.Style {

	}

	public static final ProvidesKey<ContentTypeRPCProxy> CONTENT_TYPE_KEY_PROVIDER = new ProvidesKey<ContentTypeRPCProxy>() {
		public Object getKey(ContentTypeRPCProxy item) {
			return item == null ? null : item.getId();
		}
	};

	@UiHandler("btnEdit")
	void handleButtonCancelClick(ClickEvent e) {
		GroupContentTypeSelection contentTypeSelection = new GroupContentTypeSelection(
				selectedGroupProxy);
		contentTypeSelection.setGlassEnabled(true);
		contentTypeSelection.center();
		contentTypeSelection.show();
		contentTypeSelection.setListener(new Listener() {

			public void onSave() {
				service.findByGroupId(selectedGroupProxy.getId(),
						new AsyncCallback<ArrayList<ContentTypeRPCProxy>>() {

							public void onFailure(Throwable e) {
								Window.alert("There was an error while fetching ContentTypes.");

							}

							public void onSuccess(
									ArrayList<ContentTypeRPCProxy> results) {
								ltContentTypes.clear();
								for (ContentTypeRPCProxy proxy : results) {
									ltContentTypes.addItem(proxy.getName(),
											proxy.getId().toString());
								}

							}
						});

			}
		});

	}

	boolean isNew = false;

	@UiHandler("btnSave")
	void handleButtonSaveClick(ClickEvent e) {
		GroupRequest thisRequest = requestFactory.groupRequest();
		final List<GroupProxy> data = dataProvider.getList();
		GroupProxy saveGroup;
		if (!isNew) {
			
			data.remove(selectedGroupProxy);		
			saveGroup = thisRequest.edit(selectedGroupProxy);
		}else
		{
			btnEdit.setVisible(true);
			saveGroup = thisRequest.create(GroupProxy.class);
		}
		saveGroup.setDescription(this.txtDescription.getText());
		saveGroup.setName(this.txtName.getText());
		thisRequest.persit(saveGroup).fire(new Receiver<GroupProxy>() {

			@Override
			public void onSuccess(GroupProxy result) {
				selectedGroupProxy = result;
				data.add(result);
				btnDelete.setVisible(true);
			}
		});


	}

	@UiHandler("btnDelete")
	void handleButtonDeleteClick(ClickEvent e) {
		if (Window.confirm("Are you sure you want to delete this group?")) {
			requestFactory.groupRequest().remove(selectedGroupProxy.getId())
					.fire(new Receiver<Boolean>() {
						@Override
						public void onFailure(ServerFailure error) {
							Window.alert("There was an error while deleting group.");
						}

						@Override
						public void onSuccess(Boolean result) {
							final List<GroupProxy> data = dataProvider
									.getList();
							data.clear();
							requestFactory.groupRequest().findAll()
									.fire(new Receiver<List<GroupProxy>>() {
										@Override
										public void onFailure(
												ServerFailure error) {
											Window.alert("There was an error while fetching groups.");
										}

										@Override
										public void onSuccess(
												List<GroupProxy> results) {
											totalsGroupSpan.setInnerText(results.size() + " groups");
											data.clear();
											data.addAll(results);
										}
									});
							cellList.redraw();
							editPanel.setVisible(false);
							overviewPanel.setVisible(true);
						}
					});
		}

	}
	@UiHandler("btnNew")
	void handleButtonNewClick(ClickEvent e) {
		
		if(selectedGroupProxy != null && (!selectedGroupProxy.getName().equalsIgnoreCase(txtName.getText().trim()) ||!selectedGroupProxy.getDescription().equalsIgnoreCase(txtDescription.getText().trim())))
		{
			if(Window.confirm("Your changes to this group will be lost if you don't save them."))
				createNew();
		}
		else
			createNew();
		
	
	}
	
	private void createNew()
	{
		btnDelete.setVisible(false);
		btnSave.setVisible(true);
		isNew = true;
		clearForm();
		editPanel.setVisible(true);
		btnEdit.setVisible(false);
		overviewPanel.setVisible(false);
	}

}
